#pragma once

#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <string_view>
#include <thread>
#include <chrono>
#include <cassert>

#include "./BenchmarkWorkloadBase.h"

using namespace std;
using namespace std::chrono_literals;


struct TestSetBase {
    const string name;

    vector<unique_ptr<BenchmarkWorkloadBase>> test_cases;

    /**
     * 
     * @param name should always be __FILE__ of the benchmark module implementation
     */
    explicit TestSetBase(const string_view name) : name(name)
    { }

    void operator()()
    {
        std::cout << "Running testset " << name << std::endl;

        assert(!test_cases.empty());

        for (const auto &t : test_cases) {
            std::cout << "Test case " << t->name
                << " (thrd=" << t->thread_nr
                << ", minruns=" << t->minimum_runs << ") ... "
                << std::flush;

            std::this_thread::sleep_for(.5s);
            t->init(this);
            // std::cout << "[init] " << std::flush;

            std::this_thread::sleep_for(.5s);
            (*t)(this);
            // std::cout << "[run] " << std::flush;

            t->cleanup(this);
            // std::cout << "[cleanup] " << std::flush;

            std::cout << "Finished!" << std::endl;
        }
    }

private:
    virtual void __just_to_make_this_class_polymorphic_so_it_works_with_dynamic_cast() {}
};  /* struct TestSetBase */
